﻿import threading
import configparser
import sys
import os
import time
import json
import traceback 
from init import PATH
from networks import networks
from gpio import gpio_one

global ioInfo
ioInfo={}
#io信息
def setIoInfo():
    return {"GPIO_BCM_OUT_16":["31","0"],"GPIO_BCM_OUT_21":["31","0"],"GPIO_BCM_OUT_20":["31","0"],"DS18B20":["12","未检测到DS18B20"]}
#初始化配置信息
def conf(state=0):
    #实例化
    conf = configparser.ConfigParser()
    #读取配置文件
    conf.read(PATH()+'init.conf')
    #获取sn
    sn=conf.get('networks','sn')
    #获取key
    key=conf.get('networks','key')
    #判断是否为空
    if(sn=='' or key==''):
        state=1
    #如果不为空
    if(state==1):
        sn=input('please input sn:')
        key=input('please input key:')
        conf.set('networks','sn',sn)
        conf.set('networks','key',key)
        conf.write(open(PATH()+'init.conf',"w"))
    #返回字典
    return {'sn':sn,'key':key}
#GPIO OUT 控制
def setIo(setInfo):
    #开启全局变量
    global ioInfo
    #遍历字典
    for bcm_num in setInfo:
        #判断是否是GPIO控制引脚
        if(bcm_num[0:13]=="GPIO_BCM_OUT_"):
            #获取引脚号
            gpio_num=int(bcm_num[13:])
            #控制
            gpio_one.ioMamage(gpio_num,1,int(setInfo[bcm_num][1]))
            #将状态存入字典
            ioInfo[bcm_num][1]=gpio_one.getIoInfo(gpio_num)
def getDs18b20(devName="DS18B20"):
    #开启全局变量
    global ioInfo
    while 1:
        try:
            #start = time.time()
            temp_shell=(os.popen("cat /sys/bus/w1/devices/28*/w1_slave")).read()
            #print ("read: %f s" % (time.time() - start))
            temp_start=(temp_shell.find("t="))+2
            temp=str(float(temp_shell[temp_start:-1])/1000)
            ioInfo[devName][1]=temp+'℃'
        except Exception as e:
            ioInfo[devName][1]="未检测到DS18B20"
            print(str(e))
            traceback.print_exc()
        #防止资源占用率过高导致树莓派死机
        time.sleep(0.3)
#主逻辑
def main():
    #开启全局变量
    global ioInfo
    try:
        #初始化IO信息
        ioInfo=setIoInfo()
        while 1:
            try:
                #获取初始化信息
                config=conf()
                #获取SN
                sn=config['sn']
                #获取KEY
                key=config['key']
                #防止资源占用率过高导致树莓派死机
                time.sleep(0.1)
                #初始化注册状态值
                isRegister=0
                #初始化IO状态值
                isIoInit=0
                #初始化网络连接
                if(networks.socketInit()==True):
                    #发送注册消息
                    if(networks.socketSend('{"0":"1","1":"'+sn+'","2":"'+key+'"}')==True):
                         #超时次数
                        timeOutCount=0
                        #主循环
                        while 1:
                            #是否发送了数据
                            isSendInfo=0
                            #是否退出当前循环
                            isBreak=0
                            #执行DS18B20相关操作
                            #getDs18b20()
                            #接收消息
                            data=networks.socketGet()
                            #是否收到数据
                            if(data!=False):
                                #收到数据是否为空
                                if len(data.strip())>0 :
                                    #超时清零
                                    timeOutCount=0
                                    #初始化列表
                                    dataArr=[]
                                    data_num=data.find("}{")
                                    #是否发送IO信息
                                    isReturnIoinfo=1
                                    #判断是否出现黏带情况
                                    if(data_num!=-1):
                                        print(data[0:data_num+1])
                                        #切割接收到的信息
                                        dataArr.append(json.loads(data[0:data_num+1]))
                                        #循环拆分
                                        while 1:
                                            #临时保存上一次的位置
                                            temp=data_num
                                            #分割黏带的JSON数据
                                            data_num=data.find("}{",temp+2)
                                            if(data_num==-1):
                                                dataArr.append(json.loads(data[temp+1:]))
                                                break
                                            if(data_num>0):
                                                info=json.loads(data[temp+1:data_num+1])
                                                if(info['0']=='2' and info['1']=='1'):
                                                    if(info['2']!=''):
                                                        isReturnIoinfo=0
                                                dataArr.append(info)
                                    else:
                                        dataArr.append(json.loads(data))
                                    for dataResolve in dataArr:
                                        #指令错误
                                        if(dataResolve['0']=='-1'):
                                            print('CMD Error')
                                        #判断是否注册过
                                        elif(isRegister==0):
                                            if(dataResolve['0']=='1'):
                                                #如果注册失败
                                                if(dataResolve['1']!='1'):
                                                    print('Register failure')
                                                    #提示输入SN
                                                    conf(1)
                                                    isBreak=1
                                                    break
                                                print('Register success')
                                                #更改为已注册状态
                                                isRegister=1
                                                #获取IO信息
                                                if(networks.socketSend('{"0":"2"}')==False):
                                                    isSendInfo=1
                                                    isBreak=1
                                                    break
                                        #判断是否初始化过
                                        elif(isIoInit==0):
                                            #是否为IO信息接收指令
                                            if(dataResolve['0']=='2'):
                                                #如果获取IO信息失败
                                                if(dataResolve['1']!='1'):
                                                    print('Get I/O info failure')
                                                    isBreak=1
                                                    break
                                                #判断获取到的IO信息是否为空
                                                if(dataResolve['2']!=''):
                                                    #设置IO信息
                                                    setIo(dataResolve['2'])
                                                    #发送IO信息数据包
                                                    if(networks.socketSend('{"0":"3","1":'+json.dumps(ioInfo)+'}')==False):
                                                        isBreak=1
                                                    isSendInfo=1
                                                else:
                                                    #设置IO信息
                                                    setIo(ioInfo)
                                                    #发送IO信息数据包
                                                    if(networks.socketSend('{"0":"3","1":'+json.dumps(ioInfo)+'}')==False):
                                                        isBreak=1
                                                    isSendInfo=1
                                                print('Get I/O info success')
                                            #IO信息数据包发送是否成功
                                            elif(dataResolve['0']=='3'):
                                                #IO数据包发送成功
                                                if(dataResolve['1']=='1'):
                                                    #更改为已初始化状态
                                                    isIoInit=1
                                        #如果注册过而且IO初始化过则进入循环接收模式
                                        elif(isRegister==1 and isIoInit==1):
                                            #等待IO控制命令
                                            if(dataResolve['0']=='2' and dataResolve['1']=='1'):
                                                if(dataResolve['2']!=''):
                                                    #IO控制
                                                    setIo(dataResolve['2'])
                                                    #获取温度
                                                    #getDs18b20()
                                                    if(networks.socketSend('{"0":"3","1":'+json.dumps(ioInfo)+'}')==False):
                                                        isBreak=1
                                                    isSendInfo=1
                                                else:
                                                    if(isReturnIoinfo==1):
                                                        #已经返回过
                                                        isReturnIoinfo=0
                                                        #获取温度
                                                        #getDs18b20()
                                                        #发送IO信息数据包
                                                        if(networks.socketSend('{"0":"3","1":'+json.dumps(ioInfo)+'}')==False):
                                                            isBreak=1
                                                        isSendInfo=1
                                            #更新WIFI配置信息 --- 暂时屏蔽掉
                                            #elif(dataResolve['0']=='5'):
                                                #if(dataResolve['1']=='1'):
                                                    #networks.update(dataResolve['2'],dataResolve['3'])
                                                    #break
                                        #没有注册则退出
                                        else:
                                            print("Not CMD")
                            else:
                                if(networks.socketSend('{"0":"3","1":'+json.dumps(ioInfo)+'}')==False):
                                    isBreak=1
                                isSendInfo=1
                                if(timeOutCount>2):
                                    isBreak=1
                                else:
                                    timeOutCount+=1
                            #防止资源占用率过高导致树莓派死机
                            time.sleep(0.01)
                            if(isSendInfo==0):
                                #防止资源占用率过高导致树莓派死机
                                #time.sleep(0.01)
                                #发送心跳包
                                if(networks.socketSend('{"0":"0"}')==False):
                                    isBreak=1
                             #判断是否退出循环
                            if(isBreak==1):
                                break
                    #关闭网络连接
                    networks.socketClose()
            except Exception as e:
                #关闭socket连接
                networks.socketClose()
                print(str(e))
                traceback.print_exc()
    except Exception as e:
        print(str(e))
        traceback.print_exc()
if __name__ == '__main__':
    temp=threading.Thread(target=getDs18b20,name='getDs18b20')  
    temp.start()
    while True:
        main()
